Skip to content

feat(config): deduplicate plugins by name with priority-based resolution#5957

Merged
rekram1-node merged 1 commit into
anomalyco:devfrom
devxoul:plugin-unique
Jan 9, 2026
Merged

feat(config): deduplicate plugins by name with priority-based resolution#5957
rekram1-node merged 1 commit into
anomalyco:devfrom
devxoul:plugin-unique

Conversation

@devxoul

@devxoul devxoul commented Dec 22, 2025

Copy link
Copy Markdown
Contributor

Summary

Problem

Previously, if the same plugin existed in both opencode.json and .opencode/plugin/ directory, both would be loaded.

  • Example: oh-my-opencode@2.4.3 (npm) + oh-my-opencode.js (local) → both executed

Solution

  • getPluginName: Extract canonical name from plugin specifier (supports file:// URLs, npm packages, scoped packages)
  • deduplicatePlugins: Deduplicate by name, later entries (higher priority) win

Priority (highest to lowest)

  1. Local plugin/ directory
  2. Local opencode.json
  3. Global plugin/ directory
  4. Global opencode.json

Tests

  • Unit tests for getPluginName (file URLs, npm packages, scoped packages)
  • Unit tests for deduplicatePlugins (priority resolution, order preservation)
  • Integration test for local plugin overriding global config

Comment thread packages/opencode/src/config/config.ts Outdated
export function getPluginName(plugin: string): string {
if (plugin.startsWith("file://")) {
const filename = path.basename(new URL(plugin).pathname)
return filename.replace(/\.(ts|js)$/, "")

@rekram1-node rekram1-node Dec 23, 2025

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

instead of regex maybe use path parse?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rekram1-node makes sense. Updated the implementation to use path.parse() instead.

Comment thread packages/opencode/src/config/config.ts Outdated
* we reverse, deduplicate (keeping first occurrence), then restore order.
*/
export function deduplicatePlugins(plugins: string[]): string[] {
const seen = new Set<string>()

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why create a set and array? You can convert a set to array pretty easily:

 Array.from(seen.values())

@devxoul devxoul Dec 23, 2025

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rekram1-node The Set and Array store different values:

  • seenNames: canonical plugin names for duplicate detection (e.g., "oh-my-opencode")
  • uniqueSpecifiers: full plugin specifiers to return (e.g., "oh-my-opencode@2.4.3", "file:///path/to/plugin.js")

For clarity, I updated the variable names and added some comments.

@devxoul

devxoul commented Dec 23, 2025

Copy link
Copy Markdown
Contributor Author

@rekram1-node Thanks for the review. I updated some implementation. Feel free to check when you're available!

@devxoul

devxoul commented Dec 29, 2025

Copy link
Copy Markdown
Contributor Author

Just rebased the latest dev branch and resolved conflicts.

@junhoyeo

junhoyeo commented Jan 9, 2026

Copy link
Copy Markdown

this pr is genius

@github-actions

github-actions Bot commented Jan 9, 2026

Copy link
Copy Markdown
Contributor

Thanks for your contribution!

This PR doesn't have a linked issue. All PRs must reference an existing issue.

Please:

  1. Open an issue describing the bug/feature (if one doesn't exist)
  2. Add Fixes #<number> or Closes #<number> to this PR description

See CONTRIBUTING.md for details.

@devxoul

devxoul commented Jan 9, 2026

Copy link
Copy Markdown
Contributor Author

Fixes #7427

@rekram1-node

Copy link
Copy Markdown
Collaborator

/review

@github-actions

github-actions Bot commented Jan 9, 2026

Copy link
Copy Markdown
Contributor

lgtm

@rekram1-node

Copy link
Copy Markdown
Collaborator

can u rebase this? looks like a bunch of random commits got picked up

@devxoul

devxoul commented Jan 9, 2026

Copy link
Copy Markdown
Contributor Author

can u rebase this? looks like a bunch of random commits got picked up

sure thing, just rebased @rekram1-node

@rekram1-node

Copy link
Copy Markdown
Collaborator

/review

@github-actions

github-actions Bot commented Jan 9, 2026

Copy link
Copy Markdown
Contributor

lgtm

@rekram1-node rekram1-node merged commit 8e3ab4a into anomalyco:dev Jan 9, 2026
2 of 4 checks passed
@devxoul devxoul deleted the plugin-unique branch January 9, 2026 08:23
shuv1337 added a commit to Latitudes-Dev/shuvcode that referenced this pull request Jan 9, 2026
…ion (anomalyco#5957)

Cherry-picked from upstream 8e3ab4a.
Plugins with the same name are deduplicated with priority: local > project > global.
liorshk pushed a commit to liorshk/opencode that referenced this pull request Jan 17, 2026
triklozoid pushed a commit to triklozoid/opencode that referenced this pull request Feb 2, 2026
xywsxp pushed a commit to xywsxp/opencode that referenced this pull request Apr 24, 2026
Rwanbt pushed a commit to Rwanbt/opencode that referenced this pull request May 5, 2026
AIALRA-0 pushed a commit to AIALRA-0/opencode-turn-engine that referenced this pull request Jun 10, 2026
AIALRA-0 pushed a commit to AIALRA-0/opencode-turn-engine that referenced this pull request Jun 10, 2026
avion23 pushed a commit to avion23/opencode that referenced this pull request Jun 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Duplicate plugins loaded when same plugin exists in multiple sources

3 participants